home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software 2000
/
Software 2000 Volume 1 (Disc 1 of 2).iso
/
utilities
/
u223.dms
/
u223.adf
/
Dissolve
/
dissolve.c
< prev
next >
Wrap
C/C++ Source or Header
|
1987-06-27
|
18KB
|
708 lines
/* :bk=0 */
/****************************************************************************/
/* */
/* Dissolve.c */
/* */
/* Author: Lee M. Robertson */
/* Based on an article in the Nov '86 Doctor Dobb's Journal */
/* by Mike Morton */
/****************************************************************************/
#include "fcntl.h"
#include "exec/types.h"
#include "exec/memory.h"
#include "graphics/copper.h"
#include "graphics/gfx.h"
#include "graphics/view.h"
#include "graphics/rastport.h"
#include "hardware/blit.h"
#include "hardware/custom.h"
#include "intuition/intuition.h"
/*---------------------------------------------------------------------------
* following are definitions from the IFF specification
*-------------------------------------------------------------------------*/
struct BitMapHeader
{
UWORD w, h;
WORD x, y;
UBYTE nPlanes;
UBYTE masking;
UBYTE compression;
UBYTE pad1;
UWORD transparentColor;
UBYTE xAspect, yAspect;
WORD pageWidth, pageHeight;
};
typedef unsigned long ID;
struct Chunk
{
ID ckID;
long ckSize;
};
struct ColorRegister
{
UBYTE red, green, blue;
};
#define CSIZE sizeof(chunk)
#define BMHDSIZE sizeof( struct BitMapHeader)
#define mskNone 0
#define mskHasMask 1
#define mskHasTransparentColor 2
#define mskLasso 3
#define cmpNone 0 /* file is not compressed */
#define cmpByteRun1 1 /* file is Run Length Encoded */
#define MakeID(a,b,c,d) ( (long)(a)<<24 | (long)(b)<<16 | (long)(c)<<8 | (d) )
#define FORM MakeID('F','O','R','M')
#define ILBM MakeID('I','L','B','M')
#define LIST MakeID('L','I','S','T')
#define BODY MakeID('B','O','D','Y')
#define BMHD MakeID('B','M','H','D')
#define CMAP MakeID('C','M','A','P')
/*---------------------------------------------------------------------------
* Picture structure - this contains all the revalent data for a picture file
*-------------------------------------------------------------------------*/
/* define for the # of bytes in the color register map */
#define CMSIZE 3*32
struct picture
{
int numcolors; /* # of valid colors */
int fd; /* the file # for this file */
struct BitMap *bm; /* a bitmap to store the picture */
long bodysize; /* # of bytes in the body data */
struct BitMapHeader bmhd;
UBYTE cmap[CMSIZE]; /* the color values for this picture */
/* don't use the ColorRegister structure if using Aztec 'C' */
};
struct picture pic1,pic2; /* some picture sturcts */
struct BitMap BitMap; /* bitmap to read pictue into */
struct GfxBase *GfxBase;
struct IntuitionBase *IntuitionBase;
struct Window *Window;
struct Screen *Screen;
struct ViewPort *vp,*ViewPortAddress();
void *OpenLibrary();
void *GetMsg();
void *AllocMem();
void *OpenScreen();
void *OpenWindow();
#define INTUITION_REV 29L
#define GRAPHICS_REV 29L
struct NewWindow NewWindow =
{
0, /* left edge */
0, /* top edge */
320, /* width */
200, /* heigth */
0,1, /* pen's */
/* IDCmpFlags */
RAWKEY | MOUSEBUTTONS | CLOSEWINDOW,
/* flags */
RMBTRAP | WINDOWCLOSE | BACKDROP | NOCAREREFRESH | BORDERLESS | ACTIVATE,
0, /* gadget list */
0, /* check mark */
0, /* title pointer */
0, /* screen pointer */
0, /* bitmap pointer */
0,0, /* minimum sizes */
0,0, /* maximum sizes */
CUSTOMSCREEN,
};
struct NewScreen NewScreen =
{
0, /* left edge */
0, /* top edge */
320, /* width */
200, /* heigth */
5, /* depth */
0,1, /* pen's */
0, /* view modes */
CUSTOMSCREEN, /* type */
0, /* font */
(UBYTE *)"Screen", /* title */
0, /* gagets */
0, /* bitmap */
};
/*---------------------------------------------------------------------------
* main()
*-------------------------------------------------------------------------*/
main(argc,argv)
int argc;
char *argv[];
{
char *open_pic();
char *rd_bmap();
char *errmsg;
int speed;
register int i;
register long psize; /* the plane size in bytes */
register char *arg;
register char *filename;
if(argc < 2)
{
printf("Usage: Dissolve filename [ -# ]\n");
exit(0);
}
for( i=1; i < argc; i++ )
{
argv++;
arg = *argv;
if( *arg == '-' )
speed = atoi( arg + 1 );
else
filename = arg;
}
if( speed < 100 )
speed = 1000;
open_libs(); /* open the libraries */
/* open the picture files */
if( errmsg = open_pic( filename, &pic1 ))
{
printf("%s: %s\n",errmsg,filename );
end( 10 );
}
/* setup the temp bitmap for the data */
BitMap.BytesPerRow = (pic1.bmhd.w >> 4) << 1;
BitMap.Rows = pic1.bmhd.h;
BitMap.Depth = pic1.bmhd.nPlanes;
psize = BitMap.BytesPerRow * BitMap.Rows; /* calculate the plane size */
if( psize == 0 || pic1.bmhd.nPlanes > 6 )
{
printf("Ivalid parameters: %s\n",filename);
end( 10 );
}
NewScreen.Width = pic1.bmhd.w;
NewScreen.Height = pic1.bmhd.h;
NewScreen.Depth = pic1.bmhd.nPlanes;
/* set bits for display modes */
if( NewScreen.Depth == 6 && NewScreen.Width <= 320 )
NewScreen.ViewModes |= HAM;
if( NewScreen.Height > 200 )
NewScreen.ViewModes |= LACE;
if( NewScreen.Width > 320 )
NewScreen.ViewModes |= HIRES;
Screen = OpenScreen( &NewScreen);
if( Screen == 0 )
{
printf("Can't open Screen\n");
end(10);
}
NewWindow.Screen = Screen;
NewWindow.Width = pic1.bmhd.w;
NewWindow.Height = pic1.bmhd.h;
Window = OpenWindow( &NewWindow );
if( Window == 0 )
{
printf("Can't open Window\n");
end( 10 );
}
ShowTitle( Screen, 0L ); /* hide the screen title */
vp = ViewPortAddress( Window ); /* get the windows viewport */
SetRast( Window->RPort, 0L ); /* clear the screen */
setcolors( vp, &pic1.cmap[0], pic1.numcolors );
errmsg = "No memory for BitMap";
/* Allocate memory for plane data */
for( i=0; i<BitMap.Depth; i++ )
{
if( (BitMap.Planes[i] = AllocMem( psize, MEMF_CHIP)) == 0 )
goto nomem;
}
/* Now read the picture into the temp bitmap */
errmsg = rd_bmap( &BitMap, &pic1 );
if( errmsg == 0 )
{
if( (dissolve( &BitMap, Window->RPort->BitMap, speed) ) == 0 )
{
while( get_message() == 0 )
WaitPort( Window->UserPort);
}
}
nomem:
for( i=0; i<8; i++)
{
if( BitMap.Planes[i] )
FreeMem( BitMap.Planes[i],psize );
}
if( errmsg )
printf("%s: %s\n",errmsg,filename);
end( 0 );
}
/*---------------------------------------------------------------------------
* open_pic() -- open a picture file and initialize the picture data struct
*-------------------------------------------------------------------------*/
char * open_pic( filename, pic )
char *filename; /* the picture file name */
register struct picture *pic; /* the picture data */
{
register int fd; /* the picture file descriptor */
struct Chunk chunk; /* temp for read data */
register int cmsize;
fd = open( filename, O_RDONLY); /* open the file */
if( fd == -1)
return "Can't open";
if( read(fd, &chunk, CSIZE) != CSIZE )
goto readerr;
if( chunk.ckID != FORM)
return "Not a picture file";
/* check for ILBM file */
if( read(fd, &chunk, sizeof(long) ) != sizeof(long) )
goto readerr;
if( chunk.ckID != ILBM )
return "Not an ILBM file";
if( read(fd, &chunk, CSIZE) != CSIZE )
goto readerr;
if( chunk.ckID != BMHD)
return "bit map header expected";
if( chunk.ckSize != BMHDSIZE )
return "Incorrect BMHD size";
/* read the BMHD data */
if( read( fd, &pic->bmhd, BMHDSIZE ) != BMHDSIZE )
goto readerr;
pic->numcolors = 1; /* set default color map */
/* read chunks untill body is found */
while( read(fd, &chunk, CSIZE) == CSIZE )
{
if( chunk.ckID == CMAP)
{
/* read the color map */
/* get size of the color map */
if( chunk.ckSize > CMSIZE )
cmsize = CMSIZE;
else
cmsize = chunk.ckSize;
if( read(fd, &pic->cmap[0], cmsize ) != cmsize )
goto readerr;
pic->numcolors = cmsize / 3; /* save # of colors in picture */
chunk.ckSize++;
chunk.ckSize &= ~1;
if( chunk.ckSize -= cmsize )
lseek( fd, chunk.ckSize, 1 ); /* skip rest of colormap */
}
if( chunk.ckID == BODY )
{
pic->bodysize = chunk.ckSize;
pic->fd = fd;
return 0; /* no errs */
}
/* else ignore this chunks data */
lseek(fd,chunk.ckSize,1);
}
readerr:
return "Read error";
}
/*---------------------------------------------------------------------------
* open_libs() -- open the required libraries
*-------------------------------------------------------------------------*/
open_libs()
{
if( !(IntuitionBase = OpenLibrary("intuition.library",INTUITION_REV)) )
{
printf("Can't open Intuition library\n");
exit(5);
}
if( !(GfxBase = OpenLibrary("graphics.library",GRAPHICS_REV)) )
{
printf("Can't open Graphics library\n");
CloseLibrary(IntuitionBase);
exit(5);
}
}
/*---------------------------------------------------------------------------
* end() -- cleanup and exit
*-------------------------------------------------------------------------*/
end( err )
int err;
{
/* cleanup stuff */
if( Window )
CloseWindow( Window );
if( Screen )
CloseScreen( Screen );
if( GfxBase )
CloseLibrary(GfxBase);
if( IntuitionBase )
CloseLibrary(IntuitionBase);
exit( err );
}
/*---------------------------------------------------------------------------
* setcolors() -- set the color registers
*-------------------------------------------------------------------------*/
setcolors( vp, creg, numcolors )
struct ViewPort *vp;
register UBYTE *creg; /* the color values */
int numcolors; /* the # of colors to set */
{
register ULONG r,g,b; /* the RGB color values (temporaries) */
register int i;
for(i=0; i<numcolors; i++)
{
r = *creg++ >> 4;
g = *creg++ >> 4;
b = *creg++ >> 4;
SetRGB4( vp, (long)i, (long)r, (long)g, (long)b );
}
}
/*---------------------------------------------------------------------------
*
*-------------------------------------------------------------------------*/
get_message()
{
register ULONG class;
register USHORT code;
register struct IntuiMessage *Message;
static int retval = 0;
while( Message = GetMsg(Window->UserPort) )
{
class = Message->Class;
code = Message->Code;
ReplyMsg(Message);
/* allow any key press to end program */
if( class == CLOSEWINDOW || class == RAWKEY )
retval = 1;
/* allow user to hold program with right mouse button */
else if( class == MOUSEBUTTONS && code == MENUDOWN )
WaitPort( Window->UserPort);
}
return retval;
}
/*---------------------------------------------------------------------------
* rd_bmap() -- read a picture into a bitmap
* This routine assumes the bitmap is the correct size to recieve
* the picture. No error checking is done.
*-------------------------------------------------------------------------*/
char *rd_bmap( bm, pic)
struct BitMap *bm;
struct picture *pic;
{
register UBYTE *buffer; /* the picture file data */
register UBYTE *data;
register unsigned int i;
register unsigned long size;
register int nplanes; /* # of data planes */
UBYTE *planes[8]; /* array of pointers to plane data */
void *lmalloc();
char *error;
if( !( buffer = lmalloc( pic->bodysize)) )
return "No Memory for body buffer";
error = 0; /* clear for return */
size = pic->bodysize;
data = buffer;
/* read the picture data */
while( size )
{
if( size >= 0x10000 )
i = 0xffff;
else
i = size;
if( read( pic->fd, data, i ) != i )
{
error = "Read error";
goto err;
}
data += i;
size -= i;
}
/* setup the data to pass to the decode routines */
nplanes = pic->bmhd.nPlanes;
if( pic->bmhd.masking == mskHasMask )
nplanes++; /* add 1 for the mask plane */
for( i=0; i < 8; i++ )
planes[i] = bm->Planes[i]; /* copy plane pointers */
i = (pic->bmhd.w >> 4) << 1; /* # of bytes per row */
if( pic->bmhd.compression == cmpNone )
decode0( planes,buffer,i,pic->bmhd.h,nplanes);
else if( pic->bmhd.compression == cmpByteRun1 )
decode1( planes,buffer,i,pic->bmhd.h,nplanes);
else
error = "Can't decode";
err:
free( buffer ); /* dealloc the file data buffer */
return error;
}
/*---------------------------------------------------------------------------
* decode0() -- decodes the body data with no compression
*-------------------------------------------------------------------------*/
decode0( planes,data,w,h,nplanes)
UBYTE *planes[];
register UBYTE *data;
register int w,h,nplanes;
{
register UBYTE **pp; /* pointer to current plane data */
register int pcnt; /* plane counter */
for( ; h; h--) /* for each row */
{
for( pcnt = nplanes, pp = planes; pcnt; pcnt--, pp++ )
{
if( *pp ) /* don't move the data if no destination plane */
{
movmem( data, *pp, w);
*pp += w;
}
data += w;
}
}
}
/*---------------------------------------------------------------------------
* decode1() -- decodes the body data with ByteRun1 compression
* this should really be in assembly
*-------------------------------------------------------------------------*/
decode1( planes,data,w,h,nplanes)
UBYTE *planes[];
register BYTE *data;
int w,h,nplanes;
{
register UBYTE **pp; /* pointer to current plane data */
register int pcnt; /* plane counter */
register int len;
register int n;
for( ; h; h--) /* for each row */
{
for( pcnt = nplanes, pp = planes; pcnt; pcnt--, pp++ )
{
for(n=w; n > 0; n -= len )
{
len = *data++;
if( len >= 0 )
{
len++;
if( *pp ) /* move the data if destination plane */
{
movmem( data, *pp, len);
*pp += len;
}
data += len;
}
else if( len != -128 ) /* ignore nop's */
{
len = -len;
len++;
if( *pp ) /* move the data if destination plane */
{
setmem( *pp, len, *data );
*pp += len;
}
data++;
}
else
len = 0; /* if nop */
}
}
}
}
/*---------------------------------------------------------------------------
* some global variables for the dissolve function
*-------------------------------------------------------------------------*/
unsigned long rand_mask; /* the mask value for the random # generator */
unsigned long rand_val; /* the current random # value */
unsigned long rand_tbl[] = /* the table of random mask values */
{ /* from Nov '86 DDJ p. 48 */
0,0, /* first 2 values don't work */
3,6,
0xc,0x14,
0x30,0x60,
0xb8,0x110,
0x240,0x500,
0xca0,0x1b00,
0x3500,0x6000,
0xb400,0x12000,
0x20400,0x72000,
0x90000,0x140000,
0x300000,0x420000,
0xd80000,0x1200000,
0x3880000,0x7200000,
0x9000000,0x14000000,
0x32800000,0x48000000,
0xa3000000 /* for 32 bits wide */
};
/*---------------------------------------------------------------------------
* dissolve() -- dissolve one bitmap into another
* this only works for full width bit maps
*-------------------------------------------------------------------------*/
dissolve( src, dst, speed )
struct BitMap *src,*dst;
int speed;
{
register UBYTE *mplane; /* the dissolve mask plane */
register long psize; /* the size of a plane */
register long nbits; /* # of bits in a plane */
register int done;
psize = src->BytesPerRow * src->Rows;
if( (mplane = AllocMem( psize, MEMF_CHIP | MEMF_CLEAR) ) == 0 )
return -1;
nbits = psize << 3;
nbits--; /* max bit is 1 less */
/* initialize the random number generator */
rand_val = 1;
rand_mask = rand_tbl[ bitwidth(nbits) ];
mplane[0] |= 1; /* set the first bit in the mask plane */
done = 0; /* clear done flag */
while( done == 0 )
{
done = setbits( mplane, nbits, speed );
BlitBitMapMask( src, dst, mplane );
if( get_message() )
break;
}
FreeMem( mplane, psize );
return 0;
}
/*---------------------------------------------------------------------------
* setbits() -- set random bits in a plane
*-------------------------------------------------------------------------*/
setbits( plane, maxbit, numbits )
UBYTE *plane;
unsigned long maxbit;
unsigned int numbits;
{
#asm
;register useage: d5 - max bit # to set, d4 - random generator mask
; d3 - current random value, d2 - byte offset in array for bit
; d2 - bit # to set, d1 - loop counter
regs reg d2-d5
movem.l regs,-(a7)
move.l 8(a5),a0 ;get base address of array
move.l 12(a5),d5 ;get maxbit number
move 16(a5),d1 ;get # of bits to set
move.l _rand_mask,d4
move.l _rand_val,d3
move.l #0,d0 ;clear ret val for not finished
subq #1,d1
loop
lsr.l #1,d3 ;rand_val >>= 1;
bhi ok ;bif not 0 || no carry
xor
eor.l d4,d3 ;rand_val ^= rand_mask;
ok
cmp.l d5,d3 ;if( rand_val > maxbit )
bls setbit ;go set the bit if ok
bra loop
setloop
lsr.l #1,d3 ;do the shift
bls xor ;bif need to do the exculsive or
setbit
move.l d3,d2 ;copy to temp reg
lsr.l #3,d2 ;make it a byte offset
bset d3,0(a0,d2.l) ;set the bit in the array
dbne d1,setloop ;end if bit is already set || # of bits done
beq ret
move.l #1,d0 ;set ret val for finished
ret
move.l d3,_rand_val ;save new random value
movem.l (a7)+,regs
#endasm
}
/*---------------------------------------------------------------------------
* bitwidth() -- get the # of bits in a long number
*-------------------------------------------------------------------------*/
bitwidth( n )
register unsigned long n;
{
register int w;
w = 0;
while( n )
{
w++;
n >>= 1;
}
return w;
}
/*---------------------------------------------------------------------------
*
*-------------------------------------------------------------------------*/